namespace SolidMvvm {
	using System.Collections;
	using System.Collections.Generic;
	using System.IO;

	using Newtonsoft.Json;

	using SolidMvvmInterfaces;

	public class SettingCollection : SettingBase, ISettingCollection {
		readonly List<ISetting> list = new List<ISetting>();

		public int Count
		{
			get
			{
				return list.Count;
			}
		}

		public bool IsReadOnly
		{
			get
			{
				return false;
			}
		}

		public ISetting this[int index]
		{
			get
			{
				return list[index];
			}
			set
			{
				list[index] = value;
			}
		}

		public void Add(ISetting item) {
			list.Add(item);
		}

		public void Clear() {
			list.Clear();
		}

		public bool Contains(ISetting item) {
			return list.Contains(item);
		}

		public void CopyTo(ISetting[] array, int arrayIndex) {
			list.CopyTo(array, arrayIndex);
		}

		public IEnumerator<ISetting> GetEnumerator() {
			return list.GetEnumerator();
		}

		public int IndexOf(ISetting item) {
			return list.IndexOf(item);
		}

		public void Insert(int index, ISetting item) {
			list.Insert(index, item);
		}

		public bool Remove(ISetting item) {
			return list.Remove(item);
		}

		public void RemoveAt(int index) {
			list.RemoveAt(index);
		}

		public override string ToJSONString() {
			using (var stringWriter = new StringWriter()) {
				using (var jsonTextWriter = new JsonTextWriter(stringWriter) { Formatting = Formatting.Indented }) {
					jsonTextWriter.WriteStartArray();
					foreach (var value in list)
						jsonTextWriter.WriteRawValue(value.ToJSONString());
					jsonTextWriter.WriteEnd();
				}
				return stringWriter.ToString();
			}
		}

		IEnumerator IEnumerable.GetEnumerator() {
			return GetEnumerator();
		}

		public static SettingCollection FromJsonTextReader(JsonTextReader jsonTextReader) {
			if (jsonTextReader.TokenType != JsonToken.StartArray)
				throw new GeneralException("Expected JSON StartArray token.", null);

			var settingCollection = new SettingCollection();
			while (jsonTextReader.Read() && jsonTextReader.TokenType != JsonToken.EndArray)
				switch (jsonTextReader.TokenType) {
					case JsonToken.String:
						settingCollection.Add((SettingString)(string)jsonTextReader.Value);
						break;
					case JsonToken.StartArray:
						settingCollection.Add(FromJsonTextReader(jsonTextReader));
						break;
					case JsonToken.StartObject:
						settingCollection.Add(FromJsonTextReader(jsonTextReader));
						break;
					default:
						throw new GeneralException("Expected JSON String, StartArray, or StartObject token.", null);
				}
			return settingCollection;
		}

		public void Add(SettingBase value) {
			list.Add(value);
		}
	}
}
